#!/usr/bin/env python
# @Software: PyCharm
# @Time : 2023/1/10 20:20
# @Author : v_nahuachen
# @Version：V 0.1
# @File : base_page.py
# @desc :
from minium import Callback
from cases.base import base_def


class BasePage(base_def.BaseDef):
    """
    封装公用页面基础操作方法
    """

    def hook_wx_method(self, method, selector):
        """
        封装hook wx API接口，获取回调
        :param method: API接口
        :param selector: 触发元素选择器
        :return: 信号量，回调信息
        """
        callback = Callback()

        # hook wx API接口，获取回调后执行callback
        self.mini.app.hook_wx_method(method, callback=callback.callback)
        # 点击元素
        self.mini.page.get_element(selector).tap()
        is_called = callback.wait_called(timeout=10)
        callback_args = callback.get_callback_result(10)
        # 释放hook
        self.mini.app.release_hook_wx_method(method)
        return is_called, callback_args

    def hook_native_method(self, method, selector, attr_method, value=None):
        """
        封装hook wx native原生控件弹窗处理，获取回调
        :param method: 原生控件方法
        :param selector: 触发元素选择器
        :param attr_method: 调用处理弹窗方法
        :param value: 处理弹窗方法参数值
        :return: 信号量，回调信息
        """
        callback = Callback()

        # hook 小程序API方法，获取回调后执行callback
        self.mini.app.hook_wx_method(method, callback=callback.callback)
        # 点击触发弹窗按钮
        self.mini.page.get_element(selector).tap()
        self.mini.page.wait_for(2)
        # 处理授权弹窗
        if value is None:
            # 处理授权弹窗，例如self.native.allow_get_location()
            getattr(self.mini.native, attr_method)()
        else:
            getattr(self.mini.native, attr_method)(value)

        is_called = callback.wait_called(timeout=10)
        callback_args = callback.get_callback_result(10)
        # 释放hook 小程序API方法
        self.mini.app.release_hook_wx_method(method)
        return is_called, callback_args

    def hook_current_page_method(self, method, selector, attr_method, value, param=None):
        """
        hook当前页面上的方法，获取该方法回调
        :param method: 当前页面方法
        :param selector: 触发元素选择器
        :param attr_method: 调用相应操作方法
        :param value: 相应操作方法参数值
        :param param: 相应操作方法参数名
        :return: 信号量，回调信息
        """
        callback = Callback()

        # hook指定方法，监听事件
        self.mini.app.hook_current_page_method(method, callback.callback)
        ele = self.get_element_selector(selector)
        # 调用指定方法
        if param is None:
            # 例如ele.scroll_to(x=20)
            getattr(ele, attr_method)(value)
        else:
            getattr(ele, attr_method)(x=value)
        self.mini.page.wait_for(2)
        callback_called = callback.wait_called(timeout=10)
        self.mini.logger.warn(callback_called)
        callback_args = callback.get_callback_result(10)
        self.mini.logger.warn(callback_args)

        # 释放当前方法hook
        self.mini.app.release_hook_current_page_method(method)
        return callback_called, callback_args

    def hook_current_pick_method(self, method, selector, attr_method, index, value):
        """
        hook当前页面上pick方法，获取该方法回调
        :param method: 当前页面方法
        :param selector: 触发元素选择器
        :param attr_method: 调用相应操作方法(pick)
        :param index: 相应操作方法参数，选择下标
        :param value: 相应操作方法参数值
        :return: 信号量，回调信息
        """
        callback = Callback()

        # hook指定方法，监听事件
        self.mini.app.hook_current_page_method(method, callback.callback)
        els = self.get_elements_selector(selector)
        # 点击触发
        els[index].click()
        # 用trigger模拟pick完成的动作
        getattr(els[index], attr_method)(value)
        callback_called = callback.wait_called(timeout=10)
        callback_args = callback.get_callback_result(10)
        # 释放当前方法hook
        self.mini.app.release_hook_current_page_method(method)
        return callback_called, callback_args

    def hook_native_page_method(self, method, selector, attr_method, value=None):
        """
        hook当前页面方法，触发原生弹窗并处理，获取回调
        :param method: 当前页面方法
        :param selector: 触发当前页面方法元素选择器
        :param attr_method: 处理原生弹窗方法
        :param value: 处理原生弹窗方法参数值
        :return: 信号量，回调信息
        """
        callback = Callback()

        # hook指定方法，监听事件
        self.mini.app.hook_current_page_method(method, callback.callback)
        # 点击元素
        self.get_element_selector(selector).tap()
        self.mini.page.wait_for(2)
        # 处理弹窗
        if value is None:
            # 例如self.native.allow_get_user_info()
            getattr(self.mini.native, attr_method)()
        else:
            getattr(self.mini.native, attr_method)(value)
        is_called = callback.wait_called(timeout=10)
        callback_args = callback.get_callback_result(10)
        # 释放当前方法hook
        self.mini.app.release_hook_current_page_method(method)
        return is_called, callback_args

    def mock_wx_method(self, method, expect_result):
        """
        mock wx API接口
        :param method: API接口
        :param expect_result: 预期返回信息
        :return: 回调信息
        """
        # mock 小程序API方法
        self.mini.app.mock_wx_method(method=method, result=expect_result)
        # 获取回调
        info = self.mini.app.call_wx_method(method)
        info = info.get("result", {}).get("result")
        # 去掉函数的mock
        self.mini.app.restore_wx_method(method)
        return info
